﻿using FlyingEye.Consts;
using FlyingEye.DeviceMaintenance;
using FlyingEye.DeviceMaintenance.Repositories;
using FlyingEye.Exceptions;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.ObjectMapping;

namespace FlyingEye.DeviceMaintenanceServices
{
    /// <summary>
    /// 维护记录服务
    /// </summary>
    public class MaintenanceRecordService : ApplicationService
    {
        private readonly IDevicePartCheckedResultRepository _checkedResultRepository;

        private readonly IMaintenanceRecordRepository _maintenanceRecordRepository;

        private readonly IDevicePartRepository _devicePartRepository;

        private readonly DevicePartCheckItemService _devicePartCheckItemService;


        public MaintenanceRecordService(
            IDevicePartCheckedResultRepository checkedResultRepository,
            IMaintenanceRecordRepository maintenanceRecordRepository,
            IDevicePartRepository devicePartRepository,
            IDevicePartCheckItemRepository checkItemRepository,
            DevicePartCheckItemService devicePartCheckItemService)
        {
            _checkedResultRepository = checkedResultRepository;
            _maintenanceRecordRepository = maintenanceRecordRepository;
            _devicePartRepository = devicePartRepository;
            _devicePartCheckItemService = devicePartCheckItemService;
        }

        public async Task<MaintenanceRecordResponse> GetAsync(Guid id)
        {
            var model = await _maintenanceRecordRepository.GetAsync(id);

            return ObjectMapper.Map<MaintenanceRecordModel, MaintenanceRecordResponse>(model);
        }

        public async Task<List<MaintenanceRecordResponse>> GetByDevicePartAsync(Guid partId)
        {
            var list = await _maintenanceRecordRepository.GetListAsync(item => item.DevicePartId == partId);

            if (list.Any())
            {
                return ObjectMapper.Map<List<MaintenanceRecordModel>, List<MaintenanceRecordResponse>>(list);
            }

            return new(0);
        }

        /// <summary>
        /// 获取激活状态的记录
        /// </summary>
        public async Task<MaintenanceRecordResponse?> FindActiveRecordAsync(Guid partId)
        {
            var model = await _maintenanceRecordRepository.FindAsync(item => item.DevicePartId == partId && item.IsActive);

            if (model == null)
            {
                return null;
            }

            return ObjectMapper.Map<MaintenanceRecordModel, MaintenanceRecordResponse>(model);
        }

        /// <summary>
        /// 创建一个记录
        /// </summary>
        public async Task<MaintenanceRecordResponse> InsertAsync(CreateMaintenanceRecordRequest maintenanceRecord)
        {
            var hasPart = await _devicePartRepository.AnyAsync(item => item.Id == maintenanceRecord.DevicePartId);

            if (!hasPart)
            {
                throw new ResourceNotFoundException($"部件[{maintenanceRecord.DevicePartId}]不存在。");
            }

            var hasActive = await _maintenanceRecordRepository.AnyAsync(item =>
                item.DevicePartId == maintenanceRecord.DevicePartId && item.IsActive);

            if (hasActive)
            {
                throw new BusinessOperationException($"部件[{maintenanceRecord.DevicePartId}]正在维护中。");
            }

            var model = ObjectMapper.Map<CreateMaintenanceRecordRequest, MaintenanceRecordModel>(maintenanceRecord);

            model = await _maintenanceRecordRepository.InsertAsync(model);

            await CreateCheckedItemsAsync(model);

            return ObjectMapper.Map<MaintenanceRecordModel, MaintenanceRecordResponse>(model);
        }

        /// <summary>
        /// 删除一个维护记录
        /// </summary>
        public async Task DeleteAsync(Guid recordId)
        {
            var model = await _maintenanceRecordRepository.FindAsync(recordId);

            if (model == null)
            {
                throw new ResourceNotFoundException($"维护记录[recordId]不存在。");
            }

            // 删除记录相关的校验项
            await DeleteCheckedItemsAsync(model);
        }

        public async Task CancelAsync(Guid recordId, string? reason)
        {
            var model = await _maintenanceRecordRepository.FindAsync(recordId);

            if (model == null)
            {
                throw new ResourceNotFoundException($"维护记录[{recordId}]不存在。");
            }

            if (!model.IsActive)
            {
                throw new BusinessOperationException($"记录[{recordId}]已经不在维护。");
            }

            if (model.MaintenanceStep == MaintenanceStep.COMPLETED)
            {
                throw new BusinessOperationException($"维护记录[{recordId}]已经完成。");
            }

            // 结束维护
            model.CancellationReason = reason;
            model.IsActive = false;

            await _maintenanceRecordRepository.UpdateAsync(model);
        }

        /// <summary>
        /// 关闭维护
        /// </summary>
        public async Task CloseAsync(Guid recordId)
        {
            var model = await _maintenanceRecordRepository.FindAsync(recordId);

            if (model == null)
            {
                throw new ResourceNotFoundException($"维护记录[{recordId}]不存在。");
            }

            if (!model.IsActive)
            {
                throw new BusinessOperationException($"记录[{recordId}]已经不在维护。");
            }

            if (model.MaintenanceStep != MaintenanceStep.COMPLETED)
            {
                throw new BusinessOperationException($"维护记录[{recordId}]尚未完成。");
            }

            // 结束维护
            model.IsActive = false;

            await _maintenanceRecordRepository.UpdateAsync(model);
        }

        /// <summary>
        /// 验证设备部件运行时间
        /// </summary>
        private async Task VerifyDevicePartRuntimeAsync(MaintenanceRecordModel record)
        {
            // 获取部件的运行时间，并进行验证

            await Task.CompletedTask;
        }

        /// <summary>
        /// 验证校验清单
        /// </summary>
        private async Task VerifyChecklistAsync(Guid recordId)
        {
            var list = await _checkedResultRepository.GetListAsync(item => item.MaintenanceRecordId == recordId);

            if (list.Any(item => !item.IsPassed))
            {
                throw new BusinessOperationException("校验清单未通过。");
            }
        }

        /// <summary>
        /// 设置到下一个维护步骤
        /// </summary>
        public async Task AdvanceToNextStepAsync(Guid recordId)
        {
            // 获取正在维护的记录
            var model = await _maintenanceRecordRepository.FindAsync(item => item.Id == recordId && item.IsActive);

            if (model == null)
            {
                throw new ResourceNotFoundException($"记录[{recordId}]不存在。");
            }

            if (!model.IsActive)
            {
                throw new BusinessOperationException($"记录[{recordId}]已经不在维护。");
            }

            var index = MaintenanceStep.MaintenanceSteps.ToList().IndexOf(model.MaintenanceStep);

            if (index == -1)
            {
                throw new BusinessOperationException($"无效的维护步骤[{model.MaintenanceStep}]。");
            }

            if (model.MaintenanceStep == MaintenanceStep.VERIFY_CHECKLIST)
            {
                await VerifyChecklistAsync(model.Id);
            }
            else
            if (model.MaintenanceStep == MaintenanceStep.RESET_RUNTIME)
            {
                await VerifyDevicePartRuntimeAsync(model);
            }

            model.MaintenanceStep = MaintenanceStep.MaintenanceSteps[index + 1];

            // 如果维护完成，将终止原因设置成 COMPLETED
            if (model.MaintenanceStep == MaintenanceStep.COMPLETED)
            {
                model.CancellationReason = MaintenanceStep.COMPLETED;
            }

            // 更新维护步骤
            await _maintenanceRecordRepository.UpdateAsync(model);
        }

        /// <summary>
        /// 设置到前一个维护步骤
        /// </summary>
        public async Task RevertToPreviousStepAsync(Guid recordId)
        {
            var model = await _maintenanceRecordRepository.FindAsync(recordId);

            if (model == null)
            {
                throw new ResourceNotFoundException($"记录[{recordId}]不存在。");
            }

            if (!model.IsActive)
            {
                throw new BusinessOperationException($"记录[{recordId}]已经不在维护。");
            }

            var index = MaintenanceStep.MaintenanceSteps.ToList().IndexOf(model.MaintenanceStep);

            if (index == -1)
            {
                throw new BusinessOperationException($"无效的维护步骤[{model.MaintenanceStep}]。");
            }

            if (index == 0)
            {
                throw new BusinessOperationException("部件已经在开始维护阶段。");
            }

            model.MaintenanceStep = MaintenanceStep.MaintenanceSteps[index - 1];

            // 更新维护步骤
            await _maintenanceRecordRepository.UpdateAsync(model);
        }

        /// <summary>
        /// 删除记录的所有校验项
        /// </summary>
        private async Task DeleteCheckedItemsAsync(MaintenanceRecordModel record)
        {
            await _checkedResultRepository.DeleteAsync(item => item.MaintenanceRecordId == record.Id);
        }

        /// <summary>
        /// 创建校验的项
        /// </summary>
        private async Task CreateCheckedItemsAsync(MaintenanceRecordModel record)
        {
            var checkItems = await _devicePartCheckItemService.GetByDevicePartAsync(record.DevicePartId);

            foreach (var checkItem in checkItems)
            {
                var model = new DevicePartCheckedResultModel(
                    id: GuidGenerator.Create(),
                    maintenanceRecordId: record.Id,
                    checkItemId: checkItem.Id,
                    false);

                await _checkedResultRepository.InsertAsync(model);
            }
        }
    }
}
